#ifndef EXAMPLES_CONDUCTOR_CLIENT_CONDUCTOR_H_
#define EXAMPLES_CONDUCTOR_CLIENT_CONDUCTOR_H_

#include <vector>

#include "api/media_stream_interface.h"
#include "api/peer_connection_interface.h"
#include "pc/video_track_source.h"

#include "api/audio_codecs/builtin_audio_decoder_factory.h"
#include "api/audio_codecs/builtin_audio_encoder_factory.h"
#include "api/create_peerconnection_factory.h"
#include "api/video_codecs/builtin_video_decoder_factory.h"
#include "api/video_codecs/builtin_video_encoder_factory.h"

#include "rtc_base/logging.h"
#include "rtc_base/ref_counted_object.h"
#include "rtc_base/strings/json.h"
#include "media/base/video_broadcaster.h"

namespace webrtc {
    class VideoCaptureModule;
}  // namespace webrtc

namespace {
    class VcmCapturer : public rtc::VideoSinkInterface<webrtc::VideoFrame>,  public rtc::VideoSourceInterface<webrtc::VideoFrame> {
    public:
        VcmCapturer() {}
        virtual ~VcmCapturer() {}

        void OnFrame(const webrtc::VideoFrame& frame) override {
            m_broadcaster.OnFrame(frame);
        } 

    private:

        void AddOrUpdateSink(rtc::VideoSinkInterface<webrtc::VideoFrame>* sink, const rtc::VideoSinkWants& wants) override {
            RTC_LOG(INFO) << "\n\nVcmCapturer AddOrUpdateSink\n\n";
            m_broadcaster.AddOrUpdateSink(sink, wants);
        }

        void RemoveSink(rtc::VideoSinkInterface<webrtc::VideoFrame>* sink) override {
            RTC_LOG(INFO) << "\n\nVcmCapturer RemoveSink\n\n";
            m_broadcaster.RemoveSink(sink);
        }

        rtc::VideoBroadcaster m_broadcaster;
    };

    class TrackSource : public webrtc::VideoTrackSource {
    public:
        static rtc::scoped_refptr<TrackSource> Create(VcmCapturer *capturer) {
            return new rtc::RefCountedObject<TrackSource>(capturer);
        }

        rtc::VideoSourceInterface<webrtc::VideoFrame>* source() override {
            return capturer_;
        }
        VcmCapturer *capturer_;

    protected:
        explicit TrackSource(VcmCapturer *capturer) : webrtc::VideoTrackSource(/*remote=*/false), capturer_(capturer) {}

    };
}

class Conductor : public webrtc::PeerConnectionObserver, public webrtc::CreateSessionDescriptionObserver {
public:
    Conductor();
    void Close();
    bool connection_active() const;
    Json::Value getIceCandidateList() { return iceCandidateList; }

    void createOffer(std::string &peer_id_);
    void setAnswer(const Json::Value& jmessage);
    void addIceCandidate(const Json::Value& jmessage);
    void hangUp();

    std::string sendCadateString;
    std::string peerid;
    rtc::scoped_refptr<webrtc::VideoTrackSourceInterface> videoSource;
    VcmCapturer *fake_capturer;
    bool need_hangeup;
    
protected:
    ~Conductor();
    bool InitializePeerConnection();
    bool CreatePeerConnection(bool dtls);
    void DeletePeerConnection();
    void AddTracks();

    // PeerConnectionObserver implementation.
    void OnSignalingChange(
        webrtc::PeerConnectionInterface::SignalingState new_state) override {}
    void OnAddTrack(rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver,
                    const std::vector<rtc::scoped_refptr<webrtc::MediaStreamInterface>>& streams) override;
    void OnRemoveTrack(rtc::scoped_refptr<webrtc::RtpReceiverInterface> receiver) override;
    void OnDataChannel(rtc::scoped_refptr<webrtc::DataChannelInterface> channel) override {}
    void OnRenegotiationNeeded() override {}
    void OnIceConnectionChange(webrtc::PeerConnectionInterface::IceConnectionState new_state) override {
        RTC_LOG(INFO) << __PRETTY_FUNCTION__ << " state:" << new_state;
        if ( (new_state == webrtc::PeerConnectionInterface::kIceConnectionFailed) ||
             //(new_state == webrtc::PeerConnectionInterface::kIceConnectionDisconnected) ||
             (new_state == webrtc::PeerConnectionInterface::kIceConnectionClosed) ) {
            RTC_LOG(LERROR) << __PRETTY_FUNCTION__ << " state: kIceConnectionFailed or Closed ";
            need_hangeup = true;
        }
    }
    void OnIceGatheringChange(webrtc::PeerConnectionInterface::IceGatheringState new_state) override {}
    void OnIceCandidate(const webrtc::IceCandidateInterface* candidate) override;
    void OnIceConnectionReceivingChange(bool receiving) override {}

    // CreateSessionDescriptionObserver implementation.
    void OnSuccess(webrtc::SessionDescriptionInterface* desc) override;
    void OnFailure(webrtc::RTCError error) override;

protected:
    rtc::scoped_refptr<webrtc::PeerConnectionInterface> peer_connection_;
    rtc::scoped_refptr<webrtc::PeerConnectionFactoryInterface> peer_connection_factory_;
    Json::Value iceCandidateList;
};

#endif  // EXAMPLES_CONDUCTOR_CLIENT_CONDUCTOR_H_
